package com.movitech.mobile.cz.base.common.utils;

import java.util.Date;
import java.util.HashMap;
import java.util.Map;

import javax.crypto.SecretKey;
import javax.crypto.spec.SecretKeySpec;
import javax.servlet.http.HttpServletRequest;

import com.movitech.mobile.cz.base.common.util.CommonConstants;
import com.movitech.mobile.cz.base.common.util.HeadersUtils;
import com.movitech.mobile.cz.base.common.util.StringUtils;
import com.movitech.mobile.cz.base.modules.controller.RestReturnResult;
import org.apache.commons.codec.binary.Base64;

import com.google.gson.Gson;
import com.movitech.mobile.cz.base.common.util.DateUtils;

import io.jsonwebtoken.Claims;
import io.jsonwebtoken.ExpiredJwtException;
import io.jsonwebtoken.JwtBuilder;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;
import io.jsonwebtoken.SignatureException;

public class JwtUtils {

	public static final String JWT_SECRET = "XX#$%()(#*!()!KL<><MQLMNQNQJQK sdfkjsdrow32Movitechf>?N<:{LWPW";
	public static final String JWT_ERRCODE_EXPIRED = "error_code_expired";
	public static final String JWT_ERRCODE_FAILED = "error_code_failed";
	
	/**
	 * 由字符串生成加密key
	 * @return
	 */
	public static SecretKey generalKey() {
		String stringKey = JWT_SECRET;
		byte[] encodedKey = Base64.decodeBase64(stringKey);
		SecretKey key = new SecretKeySpec(encodedKey, 0, encodedKey.length, SignatureAlgorithm.HS256.getValue());
		return key;
	}

	/**
	 * 创建jwt
	 * @param subject
	 * @param ttlMillis
	 * @return * @throws Exception
	 */
	public static String createJWT(String subject, long ttlMillis) {
		String jwtString = "";
		try {
			jwtString = createJWT(null, subject, ttlMillis);
		} catch (Exception e) {
			e.printStackTrace();
		}
		return jwtString;
	}
	
	/**
	 * 创建jwt
	 * @param
	 * @param subject
	 * @param ttlMillis
	 * @return * @throws Exception
	 */
	public static String createJWT(String jti, String subject, long ttlMillis) throws Exception {
		long nowMillis = DateUtils.getNowLong();
		Date nowDate = DateUtils.getNowDate(nowMillis);
		SecretKey key = generalKey();
		JwtBuilder builder = Jwts.builder()
				.setId(jti) //jti: jwt的唯一身份标识，主要用来作为一次性token,从而回避重放攻击
				.setIssuedAt(nowDate) //iat: jwt的签发时间
				.setSubject(subject)//sub: jwt所面向的用户
				.signWith(SignatureAlgorithm.HS256, key);
		if (ttlMillis >= 0) {
			long expMillis = nowMillis + ttlMillis;
			builder.setExpiration(DateUtils.getNowDate(expMillis));//exp: jwt的过期时间，这个过期时间必须要大于签发时间
		}
		return builder.compact();
	}

	/**
	 * 解密jwt
	 * @param jwtString
	 * @return
	 * @throws Exception
	 */
	public static CheckResult parseJWT(String jwtString) {
		CheckResult checkResult = new CheckResult();
		checkResult.setSuccess(false);
		Claims claims = null;
		try {
			SecretKey key = generalKey();
			claims = Jwts.parser().setSigningKey(key)
					.parseClaimsJws(jwtString)
					.getBody();
            checkResult.setSuccess(true);
            checkResult.setClaims(claims);
            checkResult.setSubject(claims.getSubject());
        } catch (ExpiredJwtException e) {
            checkResult.setErrorCode(JWT_ERRCODE_EXPIRED);
            checkResult.setSuccess(false);
        } catch (SignatureException e) {
            checkResult.setErrorCode(JWT_ERRCODE_FAILED);
            checkResult.setSuccess(false);
        } catch (Exception e) {
            checkResult.setErrorCode(JWT_ERRCODE_FAILED);
            checkResult.setSuccess(false);
        }
		return checkResult;
	}
	
	public static String generalSubject() {
		Map<String,Object> map = new HashMap<String,Object>();
		map.put("userName","TEST");
		map.put("password","TEST123");
		return new Gson().toJson(map);
	}
	
	public static void main(String[] args) throws Exception {
		String subject= JwtUtils.parseJWT("eyJhbGciOiJIUzI1NiJ9.eyJpYXQiOjE1MjY5NjQyNjQsInN1YiI6IntcbiAgXCJ1c2VySWRcIjogXCJTUC1CSEpTSC0wNjAwMVwiLFxuICBcInVzZXJOYW1lXCI6IFwiMzEwMTE0MDAwNzMzNjM5XCIsXG4gIFwic3VwcGxpZXJzSWRcIjogXCIxMThcIixcbiAgXCJjb21wYW55TmFtZVwiOiBcIuS4iua1t-iJvuWFi-ajruaWsOaKgOacr-aciemZkOWFrOWPuFwiXG59IiwiZXhwIjoxNTI2OTY3ODY0fQ.GnTsf6hMjfvuMAST_YNISa3iTyQ0XHJSs3gghZr-8HM").getSubject();
		System.out.println(subject);
		String jtw = JwtUtils.createJWT(subject, 1l);
		System.out.println(jtw);
		jtw = JwtUtils.createJWT(subject, 50000000l);
		System.out.println(jtw);
	}

	public static String getSubject(HttpServletRequest request){
		String token = HeadersUtils.getHeadByKey(request, "token");
		String refreshToken = HeadersUtils.getHeadByKey(request, "refresh_token");
		if(StringUtils.isNotEmpty(token)) {
			CheckResult checkResult = JwtUtils.parseJWT(token);
			if(checkResult.isSuccess()) {
				return checkResult.getSubject();
			}else {
				if(StringUtils.equalsIgnoreCase(checkResult.getErrorCode(), JwtUtils.JWT_ERRCODE_EXPIRED)) {
					if(StringUtils.isNotEmpty(refreshToken)) {
						CheckResult checkResultRefresh = JwtUtils.parseJWT(refreshToken);
						if(checkResultRefresh.isSuccess()) {
							return checkResultRefresh.getSubject();
						}
					}
				}
			}
		}
		return null;
	}
}
